import router from 'koa-router';
import BingTile from '../lib/GISServer/WMTSTile/BingTile';
import TianDiTu from '../lib/GISServer/WMTSTile/TianDiTu';
import MapResource from '../com/MapResource';
import configTool from '../com/configTool';
import url from 'url';
import Google3DTiles from '../lib/GISServer/GooglePhotorealistic3DTileSet/Google3DTiles';
import ContentTypeTool from '../lib/ContentTypeTool';
import path from 'path';
import getFilePathList from '../lib/FSTool/getFilePathList';
import FSTool from '../lib/FSTool';
import fsPromise from 'fs-promise';
import fs from 'fs';
import getDataScreenshot from '../../src/com/Playwright/getDataScreenshot';
import NetworkListener from '../../src/utils/NetworkListener';

/**
 * @swagger
 * tags:
 *   - name: 地图服务
 *     description: 地图瓦片服务和资源管理接口
 */
const mapServices = new router({prefix: '/mapServices'});

mapServices
    /**
     * @swagger
     * /mapServices/BingMaps/WMT/{z}/{x}/{y}.jpeg:
     *   get:
     *     tags: [地图服务]
     *     summary: BingMaps地图卫星影像图层
     *     description: 获取Bing地图的缓存瓦片图像
     *     produces:
     *       - image/jpeg
     *     parameters:
     *       - name: z
     *         in: path
     *         description: 缩放级别
     *         required: true
     *         type: integer
     *       - name: x
     *         in: path
     *         description: 瓦片X坐标
     *         required: true
     *         type: integer
     *       - name: y
     *         in: path
     *         description: 瓦片Y坐标
     *         required: true
     *         type: integer
     *     responses:
     *       200:
     *         description: 成功获取瓦片图像
     *         content:
     *           image/jpeg:
     *             schema:
     *               type: string
     *               format: binary
     */
    .get('/BingMaps/WMT/:z/:x/:y.jpeg', async (ctx: any) => {
        ctx.set('content-type', 'image/png');
        const z = ctx.params.z;
        const x = ctx.params.x;
        const y = ctx.params.y;

        let [err, buffer] = await BingTile.getTileFileBufferByXYZ(x, y, z);
        ctx.status = 200;
        ctx.body = buffer;
    })
    .get('/BingMaps/TMS/:z/:x/:y.jpeg', async (ctx: any) => {
        ctx.set('content-type', 'image/png');
        const z = ctx.params.z-1;
        const x = ctx.params.x;
        const y = ctx.params.y;

        let [err, buffer] = await BingTile.getTileFileBufferByXYZ(x, y, z);
        ctx.status = 200;
        ctx.body = buffer;
    })
    /**
     * @swagger
     * /mapServices/tianditu-wmts/{mapType}/{TileMatrix}/{TileCol}/{TileRow}.png:
     *   get:
     *     tags: [地图服务]
     *     summary: 天地图卫星影像图层
     *     description: 获取天地图的缓存瓦片图像
     *     produces:
     *       - image/png
     *     parameters:
     *       - name: mapType
     *         in: path
     *         description: 地图类型(cva/vec等)
     *         required: true
     *         type: string
     *       - name: TileMatrix
     *         in: path
     *         description: 缩放级别
     *         required: true
     *         type: integer
     *       - name: TileCol
     *         in: path
     *         description: 瓦片列号
     *         required: true
     *         type: integer
     *       - name: TileRow
     *         in: path
     *         description: 瓦片行号
     *         required: true
     *         type: integer
     *     responses:
     *       200:
     *         description: 成功获取瓦片图像
     *         content:
     *           image/png:
     *             schema:
     *               type: string
     *               format: binary
     *       422:
     *         description: 获取瓦片失败
     *         schema:
     *           type: object
     *           properties:
     *             error:
     *               type: string
     *               description: 错误信息
     */
    .get('/tianditu-wmts/:mapType/:TileMatrix/:TileCol/:TileRow.png', async (ctx: any) => {
        const {mapType, TileMatrix, TileCol, TileRow} = ctx.params;
        let [err, buffer] = await TianDiTu.getTileFileBuffer(mapType, TileMatrix, TileCol, TileRow);

        if (buffer) {
            ctx.set('content-type', 'image/png');
            ctx.body = buffer;
        } else {
            ctx.status = 422;
            ctx.set('content-type', 'application/json;charset=utf-8');
            ctx.body = err;
            console.warn('代理 天地图 瓦片失败', mapType, TileMatrix, TileCol, TileRow);
        }
    })
    .get('/scanWebDir', async (ctx: any) => {
        ctx.status = 200;
        ctx.set('content-type', 'application/json;charset=utf-8');
        const scanWebDir = path.join(configTool.wwwPath, 'Web/PingJie');
        ctx.body = {
            code: 200,
            data: getFilePathList(scanWebDir).map(item => item.replace(scanWebDir, ''))
        };
    })
    .get('/tile.googleapis.com/(.*)', async (ctx: any) => {

        const reqUrl = ctx.request.url.replace('/mapServices/tile.googleapis.com', '');
        const urlObj = url.parse(reqUrl, true) as any;

        const pathItem = decodeURI(urlObj.pathname).split('/').filter(item => item);
        const fullPath = '/' + pathItem.join('/');

        ctx.status = 200;
        let resBuffer, resErr;
        if (fullPath === '/v1/3dtiles/root.json') {
            const {tileSetRoot} = await Google3DTiles.getRootJson();
            resBuffer = tileSetRoot;
        } else {
            const {buffer, err} = await Google3DTiles.getBuffer(fullPath);
            resBuffer = buffer;
            resErr = err;
        }


        if (resBuffer) {
            let contentType = ContentTypeTool.getContentType(path.basename(reqUrl));
            ctx.set('content-type', contentType);
            ctx.body = resBuffer;
        } else {
            ctx.status = 500;
            ctx.set('content-type', 'application/json;charset=utf-8');
            ctx.body = {
                code: 500,
                message: '获取瓦片失败' + resErr
            };
        }
    })
    /**
     * @swagger
     * /mapServices/getMapResources:
     *   get:
     *     tags: [地图服务]
     *     summary: 获取服务器部署的地图资源
     *     description: 获取本地可用的地图资源列表，包括图层、地形、三维倾斜模型
     *     responses:
     *       200:
     *         description: 成功获取地图资源
     *         schema:
     *           type: object
     *           properties:
     *             code:
     *               type: integer
     *               example: 200
     *             meg:
     *               type: string
     *               example: "获取本地资源库地图资源成功，搜索用时：120毫秒，共搜索到：15个地图资源"
     *             data:
     *               type: array
     *               items:
     *                 type: object
     *                 properties:
     *                   type:
     *                     type: string
     *                     description: 资源类型
     *                   properties:
     *                     type: object
     *                     properties:
     *                       name:
     *                         type: string
     *                         description: 资源名称
     *                       url:
     *                         type: string
     *                         description: 资源URL(已替换为服务器IP)
     *                       type:
     *                         type: string
     *                         description: 资源类型
     */
    .get('/getMapResources', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        ctx.set('sis-format', 'on');
        ctx.status = 200;
        const readFromCache = ctx.query.readFromCache;
        const data = new Date().getTime();
        const mapResources = await MapResource.getMapResources(readFromCache !== 'false');
        const localIPAddress = configTool.baseConfig.localIPAddress;

        await fsPromise.ensureDir(path.join(configTool.appBasePath, `temp/fileOut/DataSnapshot`));

        const list = NetworkListener.getServiceUrlState();
        const online = list.find((item) => item.name === `地理编码`)?.ok;


        for (let i = 0; i < mapResources.length; i++) {
            const item = mapResources[i];
            const item_id = item.pid;

            const imgPath = path.join(configTool.appBasePath, `temp/fileOut/DataSnapshot`, item_id + '.png');

            let [err, pngBuffer] = await FSTool.readFileAsync(imgPath);
            if (err && online) {
                pngBuffer = await getDataScreenshot(item);
                pngBuffer && fs.writeFileSync(imgPath, pngBuffer);
            }

            if (item.properties && pngBuffer) {
                item.properties.dataScreenshot = 'data:image/png;base64,' + pngBuffer.toString('base64');
            }
            if (item.properties.url) {
                item.properties.url = item.properties.url.replace('127.0.0.1', localIPAddress);
            }
        }

        const passTime = new Date().getTime() - data;
        ctx.body = {
            code: 200,
            message: '获取资源库地图资源，搜索用时：' + (passTime || Math.ceil(10 + Math.random() * 10)) + '毫秒，共搜索到：' + mapResources.length + '个地图资源',
            data: mapResources
        };
    });

export default mapServices;
